/**
 * User: alesj
 * Date: 11.1.2006
 * Time: 12:21:40
 * 
 * (C) Genera Lynx d.o.o.
 */

package com.alesj.blueberry.ejb.dao.impl;

import com.alesj.blueberry.ejb.common.AbstractLogManager;
import com.alesj.blueberry.ejb.dao.BasicDAO;
import com.alesj.blueberry.par.basic.ErrorLog;
import com.alesj.blueberry.par.basic.GameObject;
import com.alesj.blueberry.par.basic.RequestEntry;
import com.alesj.blueberry.par.basic.ValidationError;
import com.alesj.blueberry.spring.games.Game;
import com.alesj.blueberry.spring.timestamp.Timestamper;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.jboss.annotation.spring.Spring;

import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.persistence.PersistenceContext;
import java.util.List;

/**
 * DAO implementation.
 * Handle transactions carefully.
 * @see TransactionAttribute
 *
 * @author <a href="mailto:ales.justin@genera-lynx.com">Ales Justin</a>
 */
@Stateless
public class BasicDAOImpl extends AbstractLogManager implements BasicDAO {

    @PersistenceContext(unitName = "bbUnit")
    private Session session;

    @Spring(jndiName = "bb-pojo", bean = "timestamper")
    private Timestamper timestamper;

    @TransactionAttribute(value = TransactionAttributeType.REQUIRES_NEW)
    public void saveRequestEntry(RequestEntry requestEntry) {
        requestEntry.setServerDate(timestamper.serverDate());
        session.save(requestEntry);
    }

    @TransactionAttribute(value = TransactionAttributeType.REQUIRES_NEW)
    public void saveValidationError(ValidationError validationError) {
        session.save(validationError);
    }

    public double findPrice(GameObject gameObject, Game game) {
        return 0; //todo
    }

    public void saveGameObject(GameObject gameObject) {
        session.save(gameObject);
    }

    public void updateSubmit(String messageId, String number) {
        RequestEntry re = findRequestEntry(messageId, number);
        updateSubmit(re, messageId + "/" + number);
    }

    public void updateDelivery(String messageId, String number) {
        RequestEntry re = findRequestEntry(messageId, number);
        updateDelivery(re, messageId + "/" + number);
    }

    @TransactionAttribute(value = TransactionAttributeType.REQUIRES_NEW)
    public void saveErrorLog(ErrorLog errorLog) {
        session.save(errorLog);
    }

    public void saveErrorLog(String messageId, String number, String exMessage) {
        RequestEntry re = findRequestEntry(messageId, number);
        ErrorLog errorLog = new ErrorLog();
        errorLog.setRequestEntry(re);
        re.addErrorLog(errorLog);
        errorLog.setServerDate(timestamper.serverDate());
        errorLog.setCommiterIndex(-1);
        errorLog.setExceptionMessage(exMessage);
        session.save(errorLog);
    }

    // helper methods

    private RequestEntry findRequestEntry(String messageId, String number) {
        if (messageId != null || number != null) {
            Criteria criteria = session.createCriteria(RequestEntry.class);
            if (messageId != null) {
                criteria.add(Restrictions.eq("messageId", messageId));
            }
            if (number != null) {
                int numberLenght = number.length();
                criteria.add(Restrictions.like("number", "%" + number.substring(numberLenght - 8)));
            }
            criteria.addOrder(Order.desc("serverDate"));
            List<RequestEntry> list = criteria.list();
            return !list.isEmpty() ? list.get(0) : null;
        } else {
            return null;
        }
    }

    private void updateSubmit(RequestEntry re, String info) {
        if (re != null) {
            re.setSubmitDate(timestamper.serverDate());
        } else {
            getLog().warn("[SubmitUpdate] No such request with id/number: " + info);
        }
    }

    private void updateDelivery(RequestEntry re, String info) {
        if (re != null) {
            re.setDeliveryDate(timestamper.serverDate());
        } else {
            getLog().warn("[DeliveryUpdate] No such request with id/number: " + info);
        }
    }

}
